/*
 * hetao - High Performance Web Server
 * author	: calvin
 * email	: calvinwilliams@163.com
 *
 * Licensed under the LGPL v2.1, see the file LICENSE in base directory.
 */

#include "hetao_in.h"
#include "hetao_socgi.h"

int ParseHttpUriToRestServiceContext( struct HttpEnv *http , struct RestServiceContext *ctx )
{
	/*
	
	/path1/path2/file
	 p1   p2
	
	/path1/path2/file?key1=value1&key2=value2
	             p1  p2
	
	                       p3    p4
	/path1/path2/file?key1=value1&key2=value2
	                  p1  p2
	
	/path1/path2/file?key1&key2=value2
	                  p1  p2
	
	*/
	
	char			*p1 = NULL ;
	char			*p2 = NULL ;
	char			*p3 = NULL ;
	char			*p4 = NULL ;
	char			*pe = NULL ;
	
	ctx->http = http ;
	
#if 0
	ctx = & (ctx->http_req) ;
	memset( ctx , 0x00 , sizeof(struct HttpRequest) );
	
	ctx->http_method = GetHttpHeaderPtr_METHOD( ctx->p_accepted_session->http_env , & (ctx->http_method_len) ) ;
	DebugLog( __FILE__ , __LINE__ , "http_method[%.*s]" , ctx->http_uri_len,ctx->http_method )
#endif
	
	ctx->http_method = GetHttpHeaderPtr_METHOD( http , & ctx->http_method_len ) ;
	DebugLog( __FILE__ , __LINE__ , "http_method[%.*s]" , ctx->http_method_len,ctx->http_method );
	
	ctx->http_uri = GetHttpHeaderPtr_URI( http , & (ctx->http_uri_len) ) ;
	DebugLog( __FILE__ , __LINE__ , "http_uri[%.*s]" , ctx->http_uri_len,ctx->http_uri );
	
	if( ctx->http_uri[0] != '/' )
		return REST_ERROR_URI_FIRST_CHARACTER;
	
	p2 = p1 = ctx->http_uri + 1 ;
	pe = ctx->http_uri + ctx->http_uri_len - 1 ;
	ctx->http_uri_paths_count = 0 ;
	while(1)
	{
		if( p2 > pe )
		{
			if( ctx->http_uri_paths_count >= sizeof(ctx->http_uri_paths)/sizeof(ctx->http_uri_paths[0]) )
				return REST_ERROR_TOO_MANY_HTTP_URI_PATHS;
			if( p2 == p1 )
			{
				ctx->http_uri_paths[ctx->http_uri_paths_count].path = "" ;
				ctx->http_uri_paths[ctx->http_uri_paths_count].path_len = 0 ;
				DebugLog( __FILE__ , __LINE__ , "p2>pe&&p2==p1 : parse out http_path[%d][%.*s]" , ctx->http_uri_paths_count , ctx->http_uri_paths[ctx->http_uri_paths_count].path_len,ctx->http_uri_paths[ctx->http_uri_paths_count].path );
				ctx->http_uri_paths_count++;
			}
			else
			{
				ctx->http_uri_paths[ctx->http_uri_paths_count].path = p1 ;
				ctx->http_uri_paths[ctx->http_uri_paths_count].path_len = p2 - p1 ;
				DebugLog( __FILE__ , __LINE__ , "p2>pe&&p2>p1 : parse out http_path[%d][%.*s]" , ctx->http_uri_paths_count , ctx->http_uri_paths[ctx->http_uri_paths_count].path_len,ctx->http_uri_paths[ctx->http_uri_paths_count].path );
				ctx->http_uri_paths_count++;
			}
			
			break;
		}
		else if( (*p2) == '/' )
		{
			if( ctx->http_uri_paths_count >= sizeof(ctx->http_uri_paths)/sizeof(ctx->http_uri_paths[0]) )
				return REST_ERROR_TOO_MANY_HTTP_URI_PATHS;
			ctx->http_uri_paths[ctx->http_uri_paths_count].path = p1 ;
			ctx->http_uri_paths[ctx->http_uri_paths_count].path_len = p2 - p1 ;
			DebugLog( __FILE__ , __LINE__ , "p2=='/' : parse out http_path[%d][%.*s]" , ctx->http_uri_paths_count , ctx->http_uri_paths[ctx->http_uri_paths_count].path_len,ctx->http_uri_paths[ctx->http_uri_paths_count].path );
			ctx->http_uri_paths_count++;
			
			p2 = p1 = p2 + 1 ;
		}
		else if( (*p2) == '?' )
		{
			if( ctx->http_uri_paths_count >= sizeof(ctx->http_uri_paths)/sizeof(ctx->http_uri_paths[0]) )
				return REST_ERROR_TOO_MANY_HTTP_URI_PATHS;
			if( p2 == p1 )
			{
				ctx->http_uri_paths[ctx->http_uri_paths_count].path = "" ;
				ctx->http_uri_paths[ctx->http_uri_paths_count].path_len = 0 ;
				DebugLog( __FILE__ , __LINE__ , "p2=='?'&&p2==p1 : parse out http_path[%d][%.*s]" , ctx->http_uri_paths_count , ctx->http_uri_paths[ctx->http_uri_paths_count].path_len,ctx->http_uri_paths[ctx->http_uri_paths_count].path );
				ctx->http_uri_paths_count++;
			}
			else
			{
				ctx->http_uri_paths[ctx->http_uri_paths_count].path = p1 ;
				ctx->http_uri_paths[ctx->http_uri_paths_count].path_len = p2 - p1 ;
				DebugLog( __FILE__ , __LINE__ , "p2=='?'&&p2>p1 : parse out http_path[%d][%.*s]" , ctx->http_uri_paths_count , ctx->http_uri_paths[ctx->http_uri_paths_count].path_len,ctx->http_uri_paths[ctx->http_uri_paths_count].path );
				ctx->http_uri_paths_count++;
			}
			
			p2 = p1 = p2 + 1 ;
			break;
		}
		else
		{
			p2++;
		}
	}
	
	ctx->http_uri_queries_count = 0 ;
	if( p2 <= pe )
	{
		while(1)
		{
			if( p2 > pe )
			{
				if( p2 > p1 )
				{
					if( ctx->http_uri_queries_count >= sizeof(ctx->http_uri_queries)/sizeof(ctx->http_uri_queries[0]) )
						return REST_ERROR_TOO_MANY_HTTP_URI_PATHS;
					ctx->http_uri_queries[ctx->http_uri_queries_count].key = p1 ;
					ctx->http_uri_queries[ctx->http_uri_queries_count].key_len = p2 - p1 ;
					ctx->http_uri_queries[ctx->http_uri_queries_count].value = "" ;
					ctx->http_uri_queries[ctx->http_uri_queries_count].value_len = 0 ;
					DebugLog( __FILE__ , __LINE__ , "p2=='&' : parse out http_query[%d][%.*s][%.*s]" , ctx->http_uri_queries_count , ctx->http_uri_queries[ctx->http_uri_queries_count].key_len,ctx->http_uri_queries[ctx->http_uri_queries_count].key , ctx->http_uri_queries[ctx->http_uri_queries_count].value_len,ctx->http_uri_queries[ctx->http_uri_queries_count].value );
					ctx->http_uri_queries_count++;
				}
				
				break;
			}
			else if( (*p2) == '&' )
			{
				if( ctx->http_uri_queries_count >= sizeof(ctx->http_uri_queries)/sizeof(ctx->http_uri_queries[0]) )
					return REST_ERROR_TOO_MANY_HTTP_URI_PATHS;
				ctx->http_uri_queries[ctx->http_uri_queries_count].key = p1 ;
				ctx->http_uri_queries[ctx->http_uri_queries_count].key_len = p2 - p1 ;
				ctx->http_uri_queries[ctx->http_uri_queries_count].value = "" ;
				ctx->http_uri_queries[ctx->http_uri_queries_count].value_len = 0 ;
				DebugLog( __FILE__ , __LINE__ , "p2=='&' : parse out http_query[%d][%.*s][%.*s]" , ctx->http_uri_queries_count , ctx->http_uri_queries[ctx->http_uri_queries_count].key_len,ctx->http_uri_queries[ctx->http_uri_queries_count].key , ctx->http_uri_queries[ctx->http_uri_queries_count].value_len,ctx->http_uri_queries[ctx->http_uri_queries_count].value );
				ctx->http_uri_queries_count++;
				
				p2 = p1 = p2 + 1 ;
			}
			else if( (*p2) == '=' )
			{
				p4 = p3 = p2 + 1 ;
				while(1)
				{
					if( p4 > pe )
					{
						if( ctx->http_uri_queries_count >= sizeof(ctx->http_uri_queries)/sizeof(ctx->http_uri_queries[0]) )
							return REST_ERROR_TOO_MANY_HTTP_URI_PATHS;
						if( p4 > p3 )
						{
							ctx->http_uri_queries[ctx->http_uri_queries_count].key = p1 ;
							ctx->http_uri_queries[ctx->http_uri_queries_count].key_len = p2 - p1 ;
							ctx->http_uri_queries[ctx->http_uri_queries_count].value = p3 ;
							ctx->http_uri_queries[ctx->http_uri_queries_count].value_len = p4 - p3 ;
							DebugLog( __FILE__ , __LINE__ , "p2=='='&&p4>pe&&p4>p3 : parse out http_query[%d][%.*s][%.*s]" , ctx->http_uri_queries_count , ctx->http_uri_queries[ctx->http_uri_queries_count].key_len,ctx->http_uri_queries[ctx->http_uri_queries_count].key , ctx->http_uri_queries[ctx->http_uri_queries_count].value_len,ctx->http_uri_queries[ctx->http_uri_queries_count].value );
							ctx->http_uri_queries_count++;
						}
						else
						{
							ctx->http_uri_queries[ctx->http_uri_queries_count].key = p1 ;
							ctx->http_uri_queries[ctx->http_uri_queries_count].key_len = p2 - p1 ;
							ctx->http_uri_queries[ctx->http_uri_queries_count].value = "" ;
							ctx->http_uri_queries[ctx->http_uri_queries_count].value_len = 0 ;
							DebugLog( __FILE__ , __LINE__ , "p2=='='&&p4>pe&&p4==p3 : parse out http_query[%d][%.*s][%.*s]" , ctx->http_uri_queries_count , ctx->http_uri_queries[ctx->http_uri_queries_count].key_len,ctx->http_uri_queries[ctx->http_uri_queries_count].key , ctx->http_uri_queries[ctx->http_uri_queries_count].value_len,ctx->http_uri_queries[ctx->http_uri_queries_count].value );
							ctx->http_uri_queries_count++;
						}
						
						break;
					}
					else if( (*p4) == '&' )
					{
						if( ctx->http_uri_queries_count >= sizeof(ctx->http_uri_queries)/sizeof(ctx->http_uri_queries[0]) )
							return REST_ERROR_TOO_MANY_HTTP_URI_PATHS;
						ctx->http_uri_queries[ctx->http_uri_queries_count].key = p1 ;
						ctx->http_uri_queries[ctx->http_uri_queries_count].key_len = p2 - p1 ;
						ctx->http_uri_queries[ctx->http_uri_queries_count].value = p3 ;
						ctx->http_uri_queries[ctx->http_uri_queries_count].value_len = p4 - p3 ;
						DebugLog( __FILE__ , __LINE__ , "p2=='='&&p4=='&' : parse out http_query[%d][%.*s][%.*s]" , ctx->http_uri_queries_count , ctx->http_uri_queries[ctx->http_uri_queries_count].key_len,ctx->http_uri_queries[ctx->http_uri_queries_count].key , ctx->http_uri_queries[ctx->http_uri_queries_count].value_len,ctx->http_uri_queries[ctx->http_uri_queries_count].value );
						ctx->http_uri_queries_count++;
						
						p2 = p1 = p4 + 1 ;
						break;
					}
					p4++;
				}
				if( p4 > pe )
					break;
			}
			else
			{
				p2++;
			}
		}
	}
	
	ctx->http_body = GetHttpBodyPtr( http , & (ctx->http_body_len) ) ;
	
	return 0;
}

struct HttpEnv *RESTGetHttpEnv( struct RestServiceContext *ctx )
{
	return ctx->http;
}

char *RESTGetHttpMethodPtr( struct RestServiceContext *ctx , int *p_http_method_len )
{
	if( p_http_method_len )
		(*p_http_method_len) = ctx->http_method_len ;
	return ctx->http_method;
}

char *RESTGetHttpUriPtr( struct RestServiceContext *ctx , int *p_http_uri_len )
{
	if( p_http_uri_len )
		(*p_http_uri_len) = ctx->http_uri_len ;
	return ctx->http_uri;
}

int RESTGetHttpUriPathsCount( struct RestServiceContext *ctx )
{
	return ctx->http_uri_paths_count;
}

char *RESTGetHttpUriPathPtr( struct RestServiceContext *ctx , int index , int *p_path_len )
{
	if( index < 1 || index > ctx->http_uri_paths_count )
		return NULL;
	
	if( p_path_len )
		(*p_path_len) = ctx->http_uri_paths[index-1].path_len ;
	return ctx->http_uri_paths[index-1].path;
}

int RESTGetHttpUriQueriesCount( struct RestServiceContext *ctx )
{
	return ctx->http_uri_queries_count;
}

char *RESTGetHttpUriQueryKeyPtr( struct RestServiceContext *ctx , int index , int *p_key_len )
{
	if( index < 1 || index > ctx->http_uri_queries_count )
		return NULL;
	
	if( p_key_len )
		(*p_key_len) = ctx->http_uri_queries[index-1].key_len ;
	return ctx->http_uri_queries[index-1].key;
}

char *RESTGetHttpUriQueryValuePtr( struct RestServiceContext *ctx , int index , int *p_value_len )
{
	if( index < 1 || index > ctx->http_uri_queries_count )
		return NULL;
	
	if( p_value_len )
		(*p_value_len) = ctx->http_uri_queries[index-1].value_len ;
	return ctx->http_uri_queries[index-1].value;
}

char *RESTGetHttpRequestBodyPtr( struct RestServiceContext *ctx , int *p_body_len )
{
	if( p_body_len )
		(*p_body_len) = ctx->http_body_len ;
	return ctx->http_body;
}

int RESTFormatHttpResponse( struct RestServiceContext *ctx , char *http_response_body , int http_response_body_len , char *http_header_format , ... )
{
	va_list			valist ;
	
	int			nret = 0 ;
	
	va_start( valist , http_header_format );
	nret = SOCGIFormatHttpResponseV( ctx->http , http_response_body , http_response_body_len , http_header_format , valist ) ;
	va_end( valist );
	
	return nret;
}

